自定义节点开发指南
概述
A1 支持用户开发自定义节点,扩展平台的功能边界。自定义节点通过编写边缘函数(Edge Function)和节点 Schema 定义,经 A1 官方审核通过后,可录入组件市场供所有用户使用。
一、开发流程
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 编写代码 │ → │ 定义Schema │ → │ 提交审核 │ → │ 上线发布 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
| 步骤 | 说明 |
|---|---|
| 编写代码 | 基于 Deno 边缘函数框架实现节点逻辑 |
| 定义 Schema | 描述节点的输入输出结构、类型和默认值 |
| 提交审核 | 将代码和 Schema 提交给 A1 官方进行审核 |
| 上线发布 | 审核通过后录入数据库,在组件市场上架 |
二、节点 Schema 定义
Schema 是节点的元数据描述,定义了节点的标识、输入输出参数等信息。
2.1 Schema 结构
{
"id": "节点唯一标识",
"data": {
"title": "节点显示标题",
"inputs": {
"type": "object",
"required": ["必填参数名数组"],
"properties": {
"参数名": {
"type": "参数类型"
}
}
},
"outputs": {
"type": "object",
"properties": {
"输出名": {
"type": "输出类型"
}
}
},
"inputsValues": {
"参数名": {
"type": "constant",
"content": "默认值"
}
}
},
"type": "节点类型标识"
}
2.2 字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | String | 是 | 节点的唯一标识符,建议使用 类型_名称_ 格式 |
data.title | String | 是 | 节点在工作流编辑器中显示的标题 |
data.inputs | Object | 是 | 输入参数的 JSON Schema 定义 |
data.inputs.required | Array | 是 | 必填参数的名称数组 |
data.inputs.properties | Object | 是 | 各参数的详细定义 |
data.outputs | Object | 是 | 输出结果的 JSON Schema 定义 |
data.inputsValues | Object | 是 | 参数的默认值配置 |
type | String | 是 | 节点类型标识,需与 id 前缀保持一致 |
2.3 支持的数据类型
| 类型 | 说明 | 示例 |
|---|---|---|
string | 字符串 | "hello" |
number | 数字 | 42, 3.14 |
integer | 整数 | 42 |
boolean | 布尔值 | true, false |
object | 对象 | {"key": "value"} |
array | 数组 | [1, 2, 3] |
三、边缘函数开发
A1 自定义节点使用 Deno Edge Runtime 运行,需要实现标准的 HTTP 接口。
3.1 函数模板
import {corsHeaders} from "../_shared/cors.ts";
Deno.serve(async (req) => {
// 1. 处理 CORS 预检请求
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
}
// 2. GET 请求:返回节点 Schema
if (req.method === "GET") {
const schema = {
id: `your_node_id_`,
type: "your_node_type",
data: {
title: `Your Node Title`,
// ... 完整的 schema 定义
}
};
return new Response(
JSON.stringify(schema),
{ headers: {...corsHeaders, "Content-Type": "application/json"} }
);
}
// 3. POST 请求:执行节点逻辑
if (req.method === "POST") {
const args = await req.json();
// 处理输入参数并返回结果
const result = processNode(args);
return new Response(
JSON.stringify(result),
{ headers: {...corsHeaders, "Content-Type": "application/json"} }
);
}
// 4. 不支持的 HTTP 方法
throw new Error("Unsupported method");
});
3.2 请求处理规范
| 方法 | 用途 | 返回 |
|---|---|---|
OPTIONS | CORS 预检 | 固定返回 "ok" |
GET | 获取 Schema | 节点的完整 JSON Schema |
POST | 执行逻辑 | 节点的执行结果 |
3.3 CORS 处理
所有响应必须包含正确的 CORS 头部:
{ headers: {...corsHeaders, "Content-Type": "application/json"} }
四、完整示例
以下是一个 JSON 数据读取节点的完整实现:
4.1 完整代码
import {corsHeaders} from "../_shared/cors.ts";
Deno.serve(async (req) => {
// CORS 预检处理
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
}
// GET: 返回节点 Schema
if (req.method === "GET") {
const res = {
id: `json_process_read_`,
type: "json_process_read",
data: {
title: `Json Process Read`,
inputsValues: {
input: {
type: "constant",
content: ""
},
read_value: {
type: "constant",
content: ""
}
},
inputs: {
type: "object",
required: ["input", "read_value"],
properties: {
input: {
type: "object"
},
read_value: {
type: "string"
}
}
},
outputs: {
type: 'object',
properties: {
result: { type: 'string' },
},
},
}
};
return new Response(
JSON.stringify(res),
{ headers: {...corsHeaders, "Content-Type": "application/json"} }
);
}
// POST: 执行节点逻辑
if (req.method === "POST") {
const args = await req.json();
const json = args.input;
return new Response(
JSON.stringify({
result: json[args.read_value],
}),
{ headers: {...corsHeaders, "Content-Type": "application/json"} }
);
}
throw new Error("Unsupported method");
});
4.2 对应的 Schema
{
"id": "json_process_read_",
"data": {
"title": "Json Process Read",
"inputs": {
"type": "object",
"required": ["input", "read_value"],
"properties": {
"input": {"type": "object"},
"read_value": {"type": "string"}
}
},
"outputs": {
"type": "object",
"properties": {
"result": {"type": "string"}
}
},
"inputsValues": {
"input": {"type": "constant", "content": ""},
"read_value": {"type": "constant", "content": ""}
}
},
"type": "json_process_read"
}
4.3 功能说明
| 输入参数 | 类型 | 说明 |
|---|---|---|
input | Object | 待读取的 JSON 对象 |
read_value | String | 要读取的键名 |
| 输出参数 | 类型 | 说明 |
|---|---|---|
result | String | 读取到的值 |
使用示例:
输入:
{
"input": {"name": "A1", "version": "1.0"},
"read_value": "name"
}
输出:
{
"result": "A1"
}
五、开发规范
5.1 命名规范
| 项目 | 规范 | 示例 |
|---|---|---|
| 节点 ID | 小写字母 + 下划线,结尾带下划线 | json_process_read_ |
| 节点类型 | 小写字母 + 下划线 | json_process_read |
| 参数名 | 小写字母 + 下划线 | read_value |
| 显示标题 | 大驼峰或短语 | Json Process Read |
5.2 错误处理
if (req.method === "POST") {
try {
const args = await req.json();
// 参数校验
if (!args.input) {
return new Response(
JSON.stringify({ error: "Missing required parameter: input" }),
{ status: 400, headers: {...corsHeaders, "Content-Type": "application/json"} }
);
}
// 业务逻辑
const result = processNode(args);
return new Response(
JSON.stringify(result),
{ headers: {...corsHeaders, "Content-Type": "application/json"} }
);
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{ status: 500, headers: {...corsHeaders, "Content-Type": "application/json"} }
);
}
}
5.3 安全注意事项
| 风险 | 防护措施 |
|---|---|
| 注入攻击 | 对用户输入进行校验和清理 |
| 资源滥用 | 设置合理的超时和资源限制 |
| 敏感数据泄露 | 不在响应中返回敏感配置信息 |
六、审核与发布
6.1 提交审核
开发完成后,请将以下材料提交给 A1 官方:
- 边缘函数代码 - 完整的 Deno 代码文件
- 节点 Schema - JSON 格式的元数据定义
- 使用说明 - 简要描述节点功能和使用方法
- 测试用例 - 输入输出示例(建议)
6.2 审核标准
| 检查项 | 说明 |
|---|---|
| 功能正确性 | 节点执行结果符合预期 |
| 接口规范性 | 遵循 A1 节点接口规范 |
| 代码质量 | 代码清晰、有必要的注释 |
| 安全性 | 无明显安全漏洞 |
| 文档完整性 | Schema 定义完整、准确 |
| 实用性 | 具有实际应用价值 |
6.3 发布流程
提交审核 → 官方评审 → 测试验证 → 录入数据库 → 组件市场上架
审核周期通常为 3-5 个工作日。审核通过后,您的节点将出现在 A1 组件市场中,供所有用户使用。
七、常见问题
Q1: 如何测试我的节点?
可以使用 curl 或 Postman 直接测试边缘函数的 HTTP 接口:
# 获取 Schema
curl https://your-function-url.deno.dev
# 执行节点逻辑
curl -X POST https://your-function-url.deno.dev \
-H "Content-Type: application/json" \
-d '{"input": {"key": "value"}, "read_value": "key"}'
Q2: 节点支持异步操作吗?
支持。在 POST 处理中使用 await 即可:
if (req.method === "POST") {
const args = await req.json();
const asyncResult = await someAsyncOperation(args);
return new Response(JSON.stringify({ result: asyncResult }), {...});
}
Q3: 如何调用外部 API?
使用标准的 fetch API:
const response = await fetch("https://api.example.com/data", {
headers: { "Authorization": "Bearer YOUR_TOKEN" }
});
const data = await response.json();
Q4: 节点执行有超时限制吗?
有的。边缘函数的默认执行超时时间为 90 秒,请确保您的节点逻辑在此时间内完成。